.\" $OpenBSD: STACK_OF.3,v 1.4 2019/06/10 09:49:48 schwarze Exp $
.\"
.\" Copyright (c) 2018 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: June 10 2019 $
.Dt STACK_OF 3
.Os
.Sh NAME
.Nm STACK_OF
.Nd variable-sized arrays of pointers, called OpenSSL stacks
.Sh SYNOPSIS
.In openssl/safestack.h
.Fn STACK_OF type
.Sh DESCRIPTION
The
.In openssl/safestack.h
header provides a fragile, unusually complicated system of
macro-generated wrappers around the functions described in the
.Xr OPENSSL_sk_new 3
manual page.
It is intended to implement superficially type-safe variable-sized
arrays of pointers, somewhat misleadingly called
.Dq stacks
by OpenSSL.
Due to the excessive number of API functions, it is impossible to
properly document this system.
In particular, calling
.Xr man 1
for any of the functions operating on stacks cannot yield any result.
.Pp
Unfortunately, application programs can hardly avoid using the concept
because several important OpenSSL APIs rely on it; see the
.Sx SEE ALSO
section for examples.
Even though both pages are more complicated than any manual page
ought to be, using the concept safely requires a complete understanding
of all the details in both this manual page and in
.Xr OPENSSL_sk_new 3 .
.Pp
The
.Fn STACK_OF
macro takes a
.Fa type
name as its argument, typically the name of a type
that has been defined as an alias for a specific
.Vt struct
type using a
.Sy typedef
declaration.
It expands to an incomplete
.Vt struct
type which is intended to represent a
.Dq stack
of objects of the given
.Fa type .
That type does not actually exist, so it is not possible to define,
for example, an automatic variable
.Ql STACK_OF(X509) my_certificates ;
it is only possible to define pointers to stacks, for example
.Ql STACK_OF(X509) *my_certificates .
The only way such pointers can ever be used is by wrapper functions
casting them to the type
.Vt _STACK *
described in
.Xr OPENSSL_sk_new 3 .
.Pp
For a considerable number of types, OpenSSL provides one wrapper
function for each function described in
.Xr OPENSSL_sk_new 3 .
The names of these wrapper functions are usually constructed by
inserting the name of the type and an underscore after the
.Sq sk_
prefix of the function name.
Usually, where the real functions take
.Vt void *
arguments, the wrappers take pointers to the
.Fa type
in questions, and where the real functions take
.Vt _STACK *
arguments, the wrappers take pointers to
.Fn STACK_OF type .
The same applies to return values.
Various exceptions to all this exist, but the above applies to
all the types listed below.
.Pp
Using the above may make sense for the following types because
public API functions exist that take stacks of these types as
arguments or return them:
.Vt ACCESS_DESCRIPTION ,
.Vt ASN1_INTEGER ,
.Vt ASN1_OBJECT ,
.Vt ASN1_TYPE ,
.Vt ASN1_UTF8STRING ,
.Vt CONF_VALUE ,
.Vt DIST_POINT ,
.Vt GENERAL_NAME ,
.Vt GENERAL_SUBTREE ,
.Vt PKCS12_SAFEBAG ,
.Vt PKCS7 ,
.Vt PKCS7_RECIP_INFO ,
.Vt PKCS7_SIGNER_INFO ,
.Vt POLICY_MAPPING ,
.Vt POLICYINFO ,
.Vt POLICYQUALINFO ,
.Vt X509 ,
.Vt X509_ALGOR ,
.Vt X509_ATTRIBUTE ,
.Vt X509_CRL ,
.Vt X509_EXTENSION ,
.Vt X509_INFO ,
.Vt X509_OBJECT ,
.Vt X509_POLICY_NODE ,
.Vt X509_PURPOSE ,
.Vt X509_REVOKED .
.Pp
Even though the OpenSSL headers declare wrapper functions for many
more types and even though the OpenSSL documentation says that users
can declare their own stack types, using
.Fn STACK_OF
with any type not listed here is strongly discouraged.
For other types, there may be subtle, undocumented differences
in syntax and semantics, and attempting to declare custom stack
types is very error prone; using plain C arrays of pointers to
the desired type is much simpler and less dangerous.
.Sh EXAMPLES
The following program creates a certificate object, puts two
pointers to it on a stack, and uses
.Xr X509_free 3
to clean up properly:
.Bd -literal
#include <err.h>
#include <stdio.h>
#include <openssl/x509.h>

int
main(void)
{
	STACK_OF(X509)	*stack;
	X509		*x;

	if ((stack = sk_X509_new_null()) == NULL)
		err(1, NULL);
	if ((x = X509_new()) == NULL)
		err(1, NULL);
	if (sk_X509_push(stack, x) == 0)
		err(1, NULL);
	if (X509_up_ref(x) == 0)
		errx(1, "X509_up_ref failed");
	if (sk_X509_push(stack, x) == 0)
		err(1, NULL);
	printf("%d pointers: %p, %p\en", sk_X509_num(stack),
	    sk_X509_value(stack, 0), sk_X509_value(stack, 1));
	sk_X509_pop_free(stack, X509_free);

	return 0;
}
.Ed
.Pp
The output looks similar to:
.Pp
.Dl 2 pointers: 0x4693ff24c00, 0x4693ff24c00
.Sh SEE ALSO
.Xr crypto 3 ,
.Xr OCSP_request_sign 3 ,
.Xr OPENSSL_sk_new 3 ,
.Xr PKCS12_parse 3 ,
.Xr PKCS7_encrypt 3 ,
.Xr SSL_CTX_set_client_CA_list 3 ,
.Xr SSL_get_ciphers 3 ,
.Xr SSL_get_peer_cert_chain 3 ,
.Xr SSL_load_client_CA_file 3 ,
.Xr X509_CRL_get_REVOKED 3 ,
.Xr X509_STORE_CTX_get0_chain 3
.Sh HISTORY
The
.Fn STACK_OF
macro first appeared in OpenSSL 0.9.3 and has been available since
.Ox 2.6 .
